package DomainLayer;

import java.util.HashSet;
import java.util.Arrays;

/**
 *
 */
public class Tracking
{
    //available copies
    private HashSet<Copy> copiesIn;
    //loaned copies
    private HashSet<Loan> loans;

    public Tracking()
    {
        copiesIn = new HashSet<Copy>();
        loans = new HashSet<Loan>();
    }

    /**
     *
     * @param copiesIn available copies for loan
     */
    public Tracking(Copy[] copiesIn)
    {
        this();
        this.copiesIn.addAll(Arrays.asList(copiesIn));
    }

    /**
     *
     * @param copiesIn available copies for loan
     * @param copiesOut loaned copies
     */
    public Tracking(Copy[] copiesIn, Loan[] loans)
    {
        this(copiesIn);
        this.loans.addAll(Arrays.asList(loans));
    }
    /**
     *
     * @param loan
     * @return true if loaning was successful
     */
    public boolean loanDVD(Loan loan)
    {
        if (copiesIn.remove(loan.getLoanCopy()))
        {
            loans.add(loan);
            return true;
        }

        return false;
    }
    
    /**
     *
     * @param copy returned copy
     * @return true if returning was successful
     */
    public boolean returnDVD(Loan loan)
    {
        if (loans.remove(loan))
        {
            copiesIn.add(loan.getLoanCopy());
            return true;
        }
        return false;
    }

    public boolean loanDVDs(Loan[] loans)
    {
        for (Loan ln: loans)
            if (!loanDVD(ln))
                return false;

        return true;
    }

    public boolean returnDVDs(Loan[] loans)
    {
        for (Loan ln: loans)
            if (!returnDVD(ln))
                return false;

        return true;
    }

    public boolean addCopy(Copy copy)
    {
        return copiesIn.add(copy);
    }

    public boolean removeCopy(Copy copy)
    {
        return copiesIn.remove(copy);
    }

    public boolean addCopies(Copy[] copies)
    {
        for (Copy cp: copies)
            if (!addCopy(cp))
                return false;

        return true;
    }

    public boolean removeCopies(Copy[] copies)
    {
        return copiesIn.removeAll(Arrays.asList(copies));
    }

    public boolean removeCopiesOfDVD(DVD dvd)
    {
        HashSet<Copy> toBeRemoved = new HashSet<Copy>();

        for (Copy cp: copiesIn)
            if (cp.getDVDName() == dvd)
                toBeRemoved.add(cp);

        return copiesIn.removeAll(toBeRemoved);
    }
    
    public Copy[] getAvailableCopiesOfDVD(DVD dvd)
    {
        HashSet<Copy> copiesOfDVD = new HashSet<Copy>();
        
        for (Copy cp: copiesIn)
            if (cp.getDVDName() == dvd)
                copiesOfDVD.add(cp);
        
        return copiesOfDVD.toArray(new Copy[copiesOfDVD.size()]);
    }
    
    public Copy[] getLoanedCopiesOfDVD(DVD dvd)
    {
        HashSet<Copy> copiesOfDVD = new HashSet<Copy>();
        
        for (Loan ln: loans)
            if (ln.getLoanCopy().getDVDName() == dvd)
                copiesOfDVD.add(ln.getLoanCopy());
        
        return copiesOfDVD.toArray(new Copy[copiesOfDVD.size()]);        
    }

    public Copy[] getCopiesOfDVD(DVD dvd)
    {
        HashSet<Copy> copiesOfDVD = new HashSet<Copy>();

        copiesOfDVD.addAll(Arrays.asList(getAvailableCopiesOfDVD(dvd)));
        copiesOfDVD.addAll(Arrays.asList(getLoanedCopiesOfDVD(dvd)));

        return copiesOfDVD.toArray(new Copy[copiesOfDVD.size()]);
    }
    public Copy getCopyBySN(int serial)
    {
        Copy cp = getAvailableCopyBySN(serial);
        
        if (cp != null)
            return cp;

        return getLoanedCopyBySN(serial);
    }

    public Integer[] getSerialsOfCopies()
    {
        Integer[] serials = new Integer[copiesIn.size()];
        Copy[] copies = copiesIn.toArray(new Copy[copiesIn.size()]);

        for (int i = 0; i < serials.length; i++)
            serials[i] = copies[i].getSerialNumber();

        return serials;
    }

    public Copy getAvailableCopyBySN(int serial)
    {
        for (Copy cp: copiesIn)
            if (cp.getSerialNumber() == serial)
                return cp;

        return null;
    }

    public Loan getLoanById(int id)
    {
        for (Loan ln: loans)
            if (ln.getId() == id)
                return ln;

        return null;
    }

    public Copy getLoanedCopyBySN(int serial)
    {
        for (Loan ln: loans)
            if (ln.getLoanCopy().getSerialNumber() == serial)
                return ln.getLoanCopy();

        return null;
    }

    public Copy getAvailableCopyByIndex(int index)
    {
        try
        {
            Copy cp = copiesIn.toArray(new Copy[copiesIn.size()])[index];
            return cp;
        }
        catch (IndexOutOfBoundsException e)
        {
            return null;
        }
    }

    public Loan getLoanByIndex(int index)
    {
        try
        {
            Loan ln = loans.toArray(new Loan[loans.size()])[index];
            return ln;
        }
        catch (IndexOutOfBoundsException e)
        {
            return null;
        }
    }

    public DVD[] getAvailableDVDs()
    {
        HashSet<DVD> dvds = new HashSet<DVD>();

        for (Copy cp: copiesIn)
            dvds.add(cp.getDVDName());

        return dvds.toArray(new DVD[dvds.size()]);
    }

    public DVD[] getLoanedDvds()
    {
        HashSet<DVD> dvds = new HashSet<DVD>();

        for (Loan ln: loans)
            dvds.add(ln.getLoanCopy().getDVDName());

        return dvds.toArray(new DVD[dvds.size()]);
    }

    public DVD[] getDvds()
    {
        HashSet<DVD> dvds = new HashSet<DVD>();
        dvds.addAll(Arrays.asList(getAvailableDVDs()));
        dvds.addAll(Arrays.asList(getLoanedDvds()));

        return dvds.toArray(new DVD[dvds.size()]);
    }

    public Person[] getRenters()
    {
        HashSet<Person> renters = new HashSet<Person>();

        for (Loan ln: loans)
            renters.add(ln.getLoanPerson());

        return renters.toArray(new Person[renters.size()]);
    }

    public DVD[] getDvdsRentedByPerson(Person person)
    {
        HashSet<DVD> dvds = new HashSet<DVD>();

        for (Loan ln: loans)
            if (ln.getLoanPerson() == person)
                dvds.add(ln.getLoanCopy().getDVDName());

        return dvds.toArray(new DVD[dvds.size()]);
    }

    public Loan[] getLoansByPerson(Person person)
    {
        HashSet<Loan> loansOfPerson = new HashSet<Loan>();

        for(Loan ln: loans)
            if (ln.getLoanPerson() == person)
                loansOfPerson.add(ln);

        return loansOfPerson.toArray(new Loan[loansOfPerson.size()]);
    }

    public Loan[] getLoans()
    {
        return loans.toArray(new Loan[loans.size()]);
    }
}
